// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of DOM3XPath
//
// DOM3XPath is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// DOM3XPath is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with DOM3XPath. If not, see <http://www.gnu.org/licenses/>.
//	
//
//   $Id$
// XPathNSResolver.cpp : Implementation of CXPathNSResolver
#include "stdafx.h"
#include <DOM3XPath.h>
#include "XPathNSResolver.h"
#include <comdef.h>
/////////////////////////////////////////////////////////////////////////////
// CXPathNSResolver

STDMETHODIMP CXPathNSResolver::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_IXPathNSResolver
	};
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (::InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}

STDMETHODIMP CXPathNSResolver::lookupNamespaceURI(BSTR prefix, BSTR *retVal)
{
	HRESULT hr = S_FALSE;
	if(prefix  == NULL)
		//This is undefined behaviour.
		hr = getAllNamespaces(retVal);
	else
	{
		//look up the namespace in the node.
		if(m_pNode)
		{
			CComBSTR sNSPath("namespace::");
			sNSPath.AppendBSTR(prefix);
			
			IXMLDOMNode * pN = NULL;
			hr = m_pNode->selectSingleNode(sNSPath,&pN);
			if(SUCCEEDED(hr) && pN)
			{			
				pN->get_text(&sNSPath);
				*retVal = sNSPath.Detach();
				::safeRelease(pN);
			}
		}
		else
			hr = E_FAIL;
	}
	return hr;
}

HRESULT CXPathNSResolver::getAllNamespaces(BSTR *pResult) const
{
/*	if(true)
	{
		CComBSTR sNSList("xmlns:xsl=\'http://www.w3.org/1999/XSL/Transform\' xmlns:xforms=\'http://www.w3.org/2002/01/xforms\' xmlns:addr=\'Address.xsd\' xmlns:ota=\'http://www.opentravel.org/OTA\');
		sNSList.CopyTo(pResult);
		return S_OK;
	}
*/ 
	HRESULT hr = S_OK;
	if(!m_pNode)
	{
		hr = S_FALSE;
	}
	else if(!!m_sNamespaceCache && m_sNamespaceCache[0])
	{
		*pResult = m_sNamespaceCache.Copy();
		hr = S_OK;
	}
	else
	{
		CComPtr<IXMLDOMNodeList> pNl;
		HRESULT hr = m_pNode->selectNodes(L"namespace::*[not(name(.)='xml')]",&pNl);
		if(pNl)
		{
			pNl->reset();
			CComPtr<IXMLDOMNode> pN;
			while(S_OK == pNl->nextNode(&pN)) //pNl returns S_FALSE when node is NULL
			{
				CComBSTR sGetXML;
				pN->get_xml(&sGetXML);
				m_sNamespaceCache +=sGetXML;
				m_sNamespaceCache += " ";
				pN.Release();
			}
		}
		//special namespace for internal functions.
		m_sNamespaceCache +=  "xmlns:xportSecretNamespaceDoNotUSE=\'http://www.x-port.net/DOM3XPath\'";
		*pResult = m_sNamespaceCache.Copy();
		hr = S_OK;
	}
	return hr;
}

HRESULT CXPathNSResolver::initialise(IXMLDOMNode * pNode)
{
	m_pNode.Release();
	
	DOMNodeType type;
	HRESULT hr = pNode->get_nodeType(&type);
	if(SUCCEEDED(hr))
	{
		switch(type)
		{
			case NODE_DOCUMENT :
			{
				CComQIPtr<IXMLDOMDocument> pDoc = pNode;
				if(pDoc)
				{
					CComPtr<IXMLDOMElement> pEl;
					pDoc->get_documentElement(&pEl);
					m_pNode = pEl;
				}
				break;
			}
			case NODE_ELEMENT :
				m_pNode = pNode;
				break;
			default:
				return E_FAIL;
		}
	}
	return hr;
}
		#ifdef COUNT_NSRESOLVER
unsigned long CXPathNSResolver::sm_Count = 0;	
		#endif
